﻿using System;
using CoreTypes;
using System.Linq;
using System.Custom;
using System.Drawing;
using System.Globalization;
using System.Custom.Window;
using System.Windows.Forms;
using System.ComponentModel;
using MainModule.Properties;
using System.Collections.Generic;

namespace MainModule
{
   public partial class LogonWindow : Window
   {
      #region Window Data

      Point FMenuPoint;
      Account FInitialAccount;
      Account FCurrentAccount;
      ServiceConfig FServiceConfig;
      IEnumerable<ServiceConfig> FForeignConfigs;
      InternetCommunicator FCommunicator = InternetCommunicator.Self;

      bool FAutoLogon = true;
      bool FAuthCurrentUser = false;
      bool FRememberPassword = true;
      string FDefaultPassword = "**********************";
      
      #endregion

      public LogonWindow()
      {
         InitializeComponent();

         FCommunicator.LogonState += communicator_LogonState;
         FCommunicator.PropertyChanged += communicator_PropertyChanged;
         FCommunicator.SyncContactsState += communicator_SyncContactsState;
         foreach (var svc in FCommunicator.ServiceDrivers) svc.SettingsChanged += service_SettingsChanged;

         FMenuPoint = new Point(0, buttonLogonOptions.Height);
         progressBar.MarqueeAnimationSpeed = Computer.OSPlatform == OS.VistaOrLater ? 10 : 50;
      }
      protected override void Dispose(bool disposing)
      {
         FCommunicator.LogonState -= communicator_LogonState;
         FCommunicator.PropertyChanged -= communicator_PropertyChanged;
         FCommunicator.SyncContactsState -= communicator_SyncContactsState;
         foreach (var svc in FCommunicator.ServiceDrivers) svc.SettingsChanged -= service_SettingsChanged;

         if (disposing && (components != null))
         {
            components.Dispose();
         }
         base.Dispose(disposing);
      }

      private void DoLogon()
      {
         ServiceConfig config = comboBoxService.SelectedItem as ServiceConfig;

         if (config == null)
         {
            comboBoxService.Select();
            comboBoxService.DroppedDown = true;
         }
         else
         {
            if (!AuthCurrentUser)
            {
               if (textBoxLogin.Text == "")
               {
                  MessageBox.Show(Resources.S_Enter_your_LoginCaption.Replace("<LoginCaption>", config.Service.LoginCaption), Text, MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                  textBoxLogin.Select();
                  return;
               }
               if (textBoxPassword.Text == "")
               {
                  MessageBox.Show(Resources.S_Enter_your_password, Text, MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                  textBoxPassword.Select();
                  return;
               }
            }
            if (FInitialAccount != null)
            {
               FInitialAccount.AutoLogon = FAutoLogon;
               FInitialAccount.RememberPassword = FRememberPassword;
               if (textBoxPassword.Text != FDefaultPassword) FInitialAccount.Password = textBoxPassword.Text;
            }
            
            FCommunicator.Logon(textBoxLogin.Text, textBoxPassword.Text == FDefaultPassword ? null : textBoxPassword.Text, config, out FCurrentAccount);
         }
      }
      internal bool Show(ServiceConfig config)
      {
         Visible = false;
         buttonLogon.Enabled = true;
         buttonClose.Enabled = true;
         progressBar.Visible = false;
         textBoxLogin.Enabled = true;
         comboBoxService.Enabled = true;
         textBoxPassword.Enabled = true;

         RefreshServices();

         ServiceConfig = config;

         return ShowDialog(FCommunicator.MainWindow as Window) == DialogResult.OK;
      }
      internal bool Show(Account account, bool modal)
      {
         FInitialAccount = account;

         Visible = false;
         buttonLogon.Enabled = true;
         buttonClose.Enabled = true;
         progressBar.Visible = false;
         textBoxLogin.Enabled = true;
         comboBoxService.Enabled = true;
         textBoxPassword.Enabled = true;

         RefreshServices();

         if (FInitialAccount == null)
         {
            ServiceConfig = null;
            textBoxLogin.Select();
            textBoxLogin.Text = "";
            textBoxPassword.Text = "";
            textBoxLogin.ReadOnly = false;
            comboBoxService.Enabled = true;
         }
         else
         {
            // Must be first assigned
            ServiceConfig = FInitialAccount.ServiceConfig;

            labelProgress.Text = "";
            textBoxLogin.ReadOnly = true;
            comboBoxService.Enabled = false;
            textBoxLogin.Text = FInitialAccount.Login;
            if (textBoxPassword.Enabled) textBoxPassword.Select();
            textBoxPassword.Text = string.IsNullOrEmpty(FInitialAccount.Password) ? "" : FDefaultPassword;
         }
         if (modal)
         {
            return ShowDialog(FCommunicator.MainWindow as Window) == DialogResult.OK;
         }
         else
         {
            Show(); return false;
         }
      }

      private bool AuthCurrentUser
      {
         get
         {
            return FAuthCurrentUser;
         }
         set
         {
            FAuthCurrentUser = value;

            if (FAuthCurrentUser)
            {
               labelProgress.Text = "";
               textBoxLogin.Enabled = false;
               textBoxPassword.Enabled = false;
               linkLabelCreateAccount.Visible = false;
               linkLabelForgotPassword.Visible = false;
               textBoxPassword.Text = FDefaultPassword;
               textBoxLogin.Text = FCommunicator.CurrentSystemLogin;
            }
            else
            {
               textBoxLogin.Enabled = true;
               textBoxPassword.Enabled = true;
               linkLabelCreateAccount.Visible = true;
               linkLabelForgotPassword.Visible = true;
               if (FInitialAccount != null) textBoxLogin.Text = FInitialAccount.Login;
               if (FInitialAccount != null) textBoxPassword.Text = FDefaultPassword;
               if (textBoxLogin.Text == "") textBoxLogin.Select();
            }
         }
      }
      private void RefreshServices()
      {
         IEnumerable<ServiceConfig> allConfigs = FCommunicator.AllConfigurations;
         IEnumerable<ServiceConfig> neutralConfigs = allConfigs.Where(c => string.IsNullOrEmpty(c.Service.Culture));
         IEnumerable<ServiceConfig> nativeConfigs = allConfigs.Where(c => !string.IsNullOrEmpty(c.Service.Culture) && c.Service.Culture.Contains(CultureInfo.CurrentCulture.TwoLetterISOLanguageName.ToLower()));
         FForeignConfigs = allConfigs.Where(c => !string.IsNullOrEmpty(c.Service.Culture) && !c.Service.Culture.Contains(CultureInfo.CurrentCulture.TwoLetterISOLanguageName.ToLower()));

         comboBoxService.Items.Clear();
         comboBoxService.Items.Add("");

         comboBoxService.Items.AddRange(nativeConfigs.Where(config => !config.ViaGateway && !config.UserDefined).ToArray());
         comboBoxService.Items.AddRange(neutralConfigs.Where(config => !config.ViaGateway && !config.UserDefined).ToArray());

         if (nativeConfigs.Count(config => config.ViaGateway && !config.UserDefined) > 0)
         {
            comboBoxService.Items.Add("--------------------------------------------------");
            comboBoxService.Items.AddRange(nativeConfigs.Where(config => config.ViaGateway && !config.UserDefined).ToArray());
         }
         if (neutralConfigs.Count(config => config.ViaGateway && !config.UserDefined) > 0)
         {
            comboBoxService.Items.AddRange(neutralConfigs.Where(config => config.ViaGateway && !config.UserDefined).ToArray());
         }
         if (allConfigs.Count(config => config.UserDefined) > 0)
         {
            comboBoxService.Items.Add("--------------------------------------------------");
            comboBoxService.Items.AddRange(allConfigs.Where(config => config.UserDefined).ToArray());
         }
         if (comboBoxService.Items.OfType<ServiceConfig>().Count() == 1)
         {
            comboBoxService.SelectedItem = comboBoxService.Items.OfType<ServiceConfig>().First();
         }
         else comboBoxService.SelectedIndex = 0;

         if (FForeignConfigs.Count() > 0)
         {
            comboBoxService.Items.Add("--------------------------------------------------");
            comboBoxService.Items.Add(Resources.S_All + "...");
         }

         FServiceConfig = null;
      }
      private ServiceConfig ServiceConfig
      {
         get
         {
            return FServiceConfig;
         }
         set
         {
            if (value != null && FServiceConfig == value) return;

            FServiceConfig = value;

            if (FServiceConfig == null)
            {
               AuthCurrentUser = false;
               
               FAutoLogon = true;
               FRememberPassword = true;
               labelProgress.Text = "";
               labelUsername.Text = Resources.S_Username + ":";
               comboBoxService.SelectedIndex = 0;
               linkLabelCreateAccount.Visible = false;
               linkLabelForgotPassword.Visible = false;
               toolTipLogin.SetToolTip(textBoxLogin, null);
               Text = Resources.S_Select_service_to_sign_in + " - " + FCommunicator.Title;
            }
            else
            {
               AuthCurrentUser = FServiceConfig.AuthCurrentUser;
               
               FAutoLogon = true;
               FRememberPassword = true;
               comboBoxService.SelectedItem = FServiceConfig;
               linkLabelCreateAccount.Visible = !AuthCurrentUser;
               linkLabelForgotPassword.Visible = !AuthCurrentUser;
               if (textBoxLogin.Text == "") textBoxLogin.Select();
               labelUsername.Text = FServiceConfig.Service.LoginCaption + ":";
               labelProgress.Text = FAuthCurrentUser ? "" : FServiceConfig.Service.Description;
               linkLabelCreateAccount.Text = Resources.S_Sign_up_to_service.Replace("<service>", FServiceConfig.ToString()) + "...";
               Text = Resources.S_Sign_in_to_service.Replace("<service>", FServiceConfig.ToString()) + " - " + FCommunicator.Title;
               toolTipLogin.SetToolTip(textBoxLogin, string.IsNullOrEmpty(FServiceConfig.Service.LoginSample) ? null : Resources.S_Example + ":  " + FServiceConfig.Service.LoginSample);
            }
         }
      }
      protected override void UpdatewWindowView()
      {
         ServiceConfig = ServiceConfig;
      }

      private void window_Shown(object sender, EventArgs e)
      {
         if (ServiceConfig != null && ServiceConfig.AuthCurrentUser) DelayedAction.Do(() => DoLogon(), 1000);
      }
      private void buttonLogon_Click(object sender, EventArgs e)
      {
         DoLogon();
      }
      private void buttonClose_Click(object sender, EventArgs e)
      {
         DialogResult = DialogResult.Cancel;
         Close();
      }
      private void itemAutoLogon_Click(object sender, EventArgs e)
      {
         FAutoLogon = !itemAutoLogon.Checked;
      }
      private void labelProgress_Click(object sender, EventArgs e)
      {
         if (labelProgress.Tag is Exception)
         {
            FCommunicator.ShowError(Resources.S_Logon_failed, labelProgress.Tag as Exception);
            labelProgress.Text = "";
            labelProgress.Tag = null;
         }
      }
      private void panelMain_Paint(object sender, PaintEventArgs e)
      {
         if (!AeroGlassVisible) FCommunicator.DrawTheme(FCommunicator.ColorTheme, e.Graphics, (sender as Control).ClientRectangle, ColorThemeObject.ToolStrip);
      }
      private void panelBase_Paint(object sender, PaintEventArgs e)
      {
         if (AeroGlassVisible) FCommunicator.DrawTheme(FCommunicator.ColorTheme, e.Graphics, (sender as Control).ClientRectangle, ColorThemeObject.ToolStrip);
         else panelBase.BackColor = Color.Transparent;
      }
      private void textBoxPassword_Enter(object sender, EventArgs e)
      {
         if (!AuthCurrentUser && textBoxPassword.Text == FDefaultPassword) textBoxPassword.Text = "";
      }
      private void textBoxPassword_Leave(object sender, EventArgs e)
      {
         if (itemRememberPassword.Checked)
         {
            if (textBoxPassword.Text == "")
            {
               if (FInitialAccount != null && !string.IsNullOrEmpty(FInitialAccount.Password)) textBoxPassword.Text = FDefaultPassword;
            }
         }
         else if (textBoxPassword.Text == FDefaultPassword)
         {
            textBoxPassword.Text = "";
         }
      }
      private void window_VisibleChanged(object sender, EventArgs e)
      {
         if (Visible) Activate();
      }
      private void itemCurrentUser_Click(object sender, EventArgs e)
      {
         AuthCurrentUser = !itemCurrentUser.Checked;
      }
      private void menuLogonOptions_Popup(object sender, EventArgs e)
      {
         itemAutoLogon.Visible = true;
         itemRememberPassword.Visible = true;
         itemSeparator1.Visible = itemCurrentUser.Visible = FServiceConfig == null ? false :
                                  FServiceConfig.SupportsFeature(ServiceFeatures.AuthCurrentUser);

         itemAutoLogon.Checked = FAutoLogon;
         itemCurrentUser.Checked = FAuthCurrentUser;
         itemRememberPassword.Checked = FRememberPassword;

         itemCurrentUser.Enabled = FServiceConfig == null ? false : !FServiceConfig.ReadOnly;
         itemRememberPassword.Enabled = !FAuthCurrentUser;
         itemAutoLogon.Enabled = true;
      }
      private void panelBottom_Paint(object sender, PaintEventArgs e)
      {
         if (!AeroGlassVisible) FCommunicator.DrawTheme(FCommunicator.ColorTheme, e.Graphics, (sender as Control).ClientRectangle, ColorThemeObject.ToolStrip);
      }
      private void textBoxLogin_KeyDown(object sender, KeyEventArgs e)
      {
         if (e.KeyCode == Keys.Enter)
         {
            e.SuppressKeyPress = true;

            if (textBoxLogin.Text != "") textBoxPassword.Select();
         }
      }
      private void service_SettingsChanged(object sender, EventArgs e)
      {
         RefreshServices();
      }
      private void buttonLogonOptions_Click(object sender, EventArgs e)
      {
         menuLogonOptions.Show(buttonLogonOptions, FMenuPoint);
      }
      private void itemRememberPassword_Click(object sender, EventArgs e)
      {
         FRememberPassword = !itemRememberPassword.Checked;
      }
      private void textBoxPassword_KeyDown(object sender, KeyEventArgs e)
      {
         if (e.KeyCode == Keys.Enter)
         {
            e.SuppressKeyPress = true;

            if (textBoxPassword.Text != "")
            {
               buttonLogon.Focus();
               buttonLogon_Click(null, null);
            }
         }
      }
      private void comboBoxService_SelectedIndexChanged(object sender, EventArgs e)
      {
         if (comboBoxService.SelectedItem is ServiceConfig)
         {
            ServiceConfig = (ServiceConfig)comboBoxService.SelectedItem;
         }
      }
      private void comboBoxService_SelectionChangeCommitted(object sender, EventArgs e)
      {
         if (comboBoxService.SelectedItem is string &&
             comboBoxService.SelectedItem.ToString().StartsWith(Resources.S_All))
         {
            comboBoxService.Items.RemoveAt(comboBoxService.SelectedIndex);
            comboBoxService.Items.AddRange(FForeignConfigs.ToArray());
            comboBoxService.SelectedIndex = -1;
            DelayedAction.Do(() => { comboBoxService.DroppedDown = true; }, 100);
         }
      }
      private void communicator_LogonState(object sender, NetworkOperationEventArgs e)
      {
         if (e.Account != FCurrentAccount) return;

         if (e.Error != null)
         {
            labelProgress.Text = Resources.S_Logon_failed + ": " + e.Error.Reason;
            labelProgress.Tag = e.Error;
            
            buttonLogon.Enabled = true;
            buttonClose.Enabled = true;
            progressBar.Visible = false;
            comboBoxService.Enabled = true;
            textBoxLogin.Enabled = !AuthCurrentUser;
            textBoxPassword.Enabled = !AuthCurrentUser;
            if (textBoxPassword.Enabled) textBoxPassword.Select();
         }
         else
         {
            if (e.State == OperationState.HostLookup ||
                e.State == OperationState.DataSending ||
                e.State == OperationState.DataSent)
            {
               labelProgress.Text = Resources.S_Logging_in;
               labelProgress.Tag = null;

               progressBar.Visible = true;
               buttonLogon.Enabled = false;
               buttonClose.Enabled = false;
               textBoxLogin.Enabled = false;
               comboBoxService.Enabled = false;
               textBoxPassword.Enabled = false;
            }
            else if (e.State == OperationState.Cancelled)
            {
               buttonLogon.Enabled = true;
               buttonClose.Enabled = true;
               progressBar.Visible = false;
               comboBoxService.Enabled = true;
               textBoxLogin.Enabled = !AuthCurrentUser;
               textBoxPassword.Enabled = !AuthCurrentUser;
               labelProgress.Text = Resources.S_Operation_was_cancelled;
            }
            else if (e.State == OperationState.Callback)
            {
               labelProgress.Text = Resources.S_Logging_in;
            }
            else if (e.State == OperationState.Completed)
            {
               labelProgress.Text = Resources.S_Logon_completed_starting_up;

               e.Account.AutoLogon = FAutoLogon;
               e.Account.Password = textBoxPassword.Text;
               e.Account.RememberPassword = FRememberPassword;
            }
         }
      }
      private void communicator_SyncContactsState(object sender, NetworkOperationEventArgs e)
      {
         if (e.Account != FCurrentAccount) return;

         if (e.Error != null)
         {
            labelProgress.Text = Resources.S_Logon_failed + ": " + e.Error.Message;
         }
         else
         {
            if (e.State == OperationState.DataSending)
            {
               labelProgress.Text = Resources.S_Loading_contacts;
            }
            else if (e.State == OperationState.Completed)
            {
               if (Modal) DialogResult = DialogResult.OK; else Close();
            }
         }
      }
      private void communicator_PropertyChanged(object sender, PropertyChangedEventArgs e)
      {
         if (e.PropertyName == "ColorTheme") Refresh();
      }
      private void linkLabelSettings_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
      {
         if (FServiceConfig != null) FServiceConfig.Service.Driver.ShowDriverSettings(FServiceConfig.ToString());
         else FCommunicator.ServiceDrivers.First(d => d.DefaultConfig.Service.ProtocolName.ToLower() == "xmpp").ShowDriverSettings("");
      }
      private void linkLabelImportProfile_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
      {
         if (FCommunicator.ImportProfile(null) > 0) Close();
      }
      private void linkLabelCreateAccount_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
      {
         FServiceConfig.Service.GoVendorPage(VendorPage.RegisterUser);
      }
      private void linkLabelForgotPassword_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
      {
         FServiceConfig.Service.GoVendorPage(VendorPage.RestorePassword);
      }
   }
}
